package com.capgemini.simpleappblanche.controller.customer;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.capgemini.simpleappblanche.controller.AbstractController;
import com.capgemini.simpleappblanche.controller.customer.model.CustomerMenu;
import com.capgemini.simpleappblanche.controller.customer.model.SearchCustomer;
import com.capgemini.simpleappblanche.controller.customer.validator.CustomerDtoValidator;
import com.capgemini.simpleappblanche.controller.customer.validator.SearchCustomerValidator;
import com.capgemini.simpleappblanche.domain.constant.CustomerConstant;
import com.capgemini.simpleappblanche.domain.constant.PermissionConstant;
import com.capgemini.simpleappblanche.dto.AgencyDto;
import com.capgemini.simpleappblanche.dto.CustomerDto;
import com.capgemini.simpleappblanche.dto.enumeration.Title;
import com.capgemini.simpleappblanche.helper.security.UserHelper;
import com.capgemini.simpleappblanche.services.IAgencyService;
import com.capgemini.simpleappblanche.services.ICustomerService;

/**
 * @author jcdorchies
 * 
 */
@Controller
@RequestMapping({"/customers"})
public class CustomerController extends AbstractController {

	@Autowired
	private ICustomerService customerService;

    @Autowired
    private IAgencyService agencyService;
	
    
    
    
	/**
	 * show list of customer
	 * @param model model
	 * @param auth auth
	 * @return view
	 */
	@PreAuthorize("hasPermission('PERM_SEARCH_CUSTOMER')")
	@RequestMapping(method = { RequestMethod.GET })
	public String showList(Model model,Authentication auth) {
		
		model.addAttribute("searchCustomer", new SearchCustomer());
		
		initSearchCustomers(model, auth);
		
		return "customer.list";
	}
	
	/**
	 * show filter to list of customer
	 * @param searchCustomer searchCustomer
	 * @param result result
	 * @param model model
	 * @param auth auth
	 * @return view
	 */
	@PreAuthorize("hasPermission('PERM_SEARCH_CUSTOMER')")
	@RequestMapping(method = { RequestMethod.POST })
	public String list(@Valid SearchCustomer searchCustomer, BindingResult result, Model model,Authentication auth) {
		log.debug("list +");
		
		if (result.hasErrors()) {
			log.debug("Error in form :" + result.getErrorCount());
            
			initSearchCustomers(model, auth);
			
            log.debug("list -");
            return "customer.list";
        }
		
		List<CustomerDto> customerDtos = new ArrayList<CustomerDto>();
		boolean maxResult = false;
		
		//not the same method, according to what user filled
		if(StringUtils.isNotEmpty(searchCustomer.getId())){
			log.debug("search by id");
		    //by ID
			CustomerDto customerDto = customerService.findById(Long.valueOf(searchCustomer.getId()));
			
			//check right on the customer
			if(!UserHelper.isAdmin(auth)){
				//check right
				//TODO
//				if(!UserHelper.hasCommonAgency(auth, customerDto.getAgencies())){
//					customerDto = null;
//				}
			}
			
			if(customerDto!=null){
				customerDtos.add(customerDto);
			}
		}else{
			log.debug("search by other parameter");
			//by Other parameters
		    
		    if(!UserHelper.isAdmin(auth)){
		        if(searchCustomer.getAgencyId() == null){
		            //if not admin add "authorized" agency and no selected agency
		            List<Long> agenciesId = UserHelper.getAgencyIdsByPermission(auth,PermissionConstant.PERM_SEARCH_CUSTOMER);
		            searchCustomer.setAgenciesId(agenciesId);
		        }else{
		            //check that user fill possible agency
		            List<Long> agencyIds = UserHelper.getAgencyIdsByPermission(auth, PermissionConstant.PERM_SEARCH_CUSTOMER);
		            if(!agencyIds.contains(searchCustomer.getAgencyId())){
		                //forbidden agency
		                searchCustomer.setAgencyId(null);
		            }
		        }
            }
		    
		    
		    customerDtos = customerService.findByCriteria(searchCustomer,CustomerConstant.NB_CUSTOMER_SEARCH_MAX+1);
			if(customerDtos!=null && customerDtos.size() > CustomerConstant.NB_CUSTOMER_SEARCH_MAX){
				customerDtos.remove(CustomerConstant.NB_CUSTOMER_SEARCH_MAX);
				maxResult = true;
			}
		}
		
		log.debug("list size :"+customerDtos.size());
		
		if(customerDtos.size() == 1){
			//redirect to detail
			CustomerDto customerDto = customerDtos.get(0);
			log.debug("list -");
			return "redirect:/customers/"+customerDto.getId();
		}
		
		model.addAttribute("customers", customerDtos);
		model.addAttribute("maxResultReached", maxResult);
		model.addAttribute("maxResult", CustomerConstant.NB_CUSTOMER_SEARCH_MAX);
		
		initSearchCustomers(model, auth);
		
		log.debug("list -");
		return "customer.list.result";
	}
	
    /**
     * Call the validator
     * @param binder call for the validator
     */
    @InitBinder(value={"searchCustomer"})
    public void initBinderList(WebDataBinder binder) {
        binder.setValidator(new SearchCustomerValidator());
    }

    /**
     * initialize view search customer
     * @param binder call for the validator
     * @param auth auth
     */
    private void initSearchCustomers(Model model,Authentication auth) {

        //if admin, load list of Agency
        if(UserHelper.isAdmin(auth)){
            model.addAttribute("agencies",agencyService.findAllActive());
        }else{
            //if user have right to read agencies, we propose them
            List<Long> agencyIds = UserHelper.getAgencyIdsByPermission(auth, PermissionConstant.PERM_SEARCH_CUSTOMER);
            if(agencyIds.size() > 0){
                List<AgencyDto> agencies = agencyService.findActiveByIds(agencyIds);
                model.addAttribute("agencies",agencies);
            }
        }
    }

    
    
    
    
	/**
	 * show detail of customer
	 * @param model
	 *            model
	 * @return view
	 */
	@RequestMapping(value={"/{id}"},method = { RequestMethod.GET })
	public String showDetail(Model model,@PathVariable(value="id") Long customerId,
			HttpServletRequest request) {
		log.debug("showDetail +");
		log.debug("customerId :"+customerId);
		
		//get customer
		CustomerDto customerDto = customerService.findById(customerId);
		model.addAttribute("customerDto", customerDto);
		
		initializeDetail(model);
		
		log.debug("showDetail -");
		return "customer.personnaldata";
	}
	/**
	 * modify detail of customer
	 * @param customerDto customerDto
	 * @param result result of binding
	 * @param model model
	 * @param customerId customerId
	 * @return view
	 */
	@RequestMapping(value={"/{id}"},method = { RequestMethod.POST})
	public String modifyDetail(@Valid CustomerDto customerDto, BindingResult result, Model model,
			@PathVariable(value="id") Long customerId) {
		log.debug("showDetail +");
		log.debug("customerId :"+customerId);
		
		if (result.hasErrors()) {
			log.debug("Error in form :" + result.getErrorCount());
			
			initializeDetail(model);
			
            log.debug("showDetail -");
            return "customer.personnaldata";
        }
		
		//save customer
		customerService.save(customerDto);
		
		log.debug("showDetail -");
		return "redirect:/customers/"+customerId;
	}
	
	
	/**
	 * create detail of customer
	 * @param model model
	 * @return view
	 */
	@RequestMapping(value={"/create"},method = { RequestMethod.GET })
	public String showEmptyDetail(Model model) {
		log.debug("showEmptyDetail +");
		
		//get customer
		model.addAttribute("customerDto", new CustomerDto());
		
		initializeDetail(model);
		
		log.debug("showEmptyDetail -");
		return "customer.personnaldata";
	}
	/**
	 * create detail of customer
	 * @param customerDto customerDto
	 * @param result result of binding
	 * @param model model
	 * @return view
	 */
	@RequestMapping(value={"/create"},method = { RequestMethod.POST})
	public String createDetail(@Valid CustomerDto customerDto, BindingResult result, Model model) {
		log.debug("createDetail +");
		
		if (result.hasErrors()) {
			log.debug("Error in form :" + result.getErrorCount());
			
			initializeDetail(model);
			
            log.debug("showDetail -");
            return "customer.personnaldata";
        }
		
		//save customer
		customerDto = customerService.save(customerDto);
		
		log.debug("showDetail -");
		return "redirect:/customers/"+customerDto.getId();
	}
	
	
	/**
	 * initialize Detail
	 * @param model model
	 */
	private void initializeDetail(Model model){
		model.addAttribute("titles",Title.values());
		
		//active customer menu
		CustomerHelper.activeMenu(model, CustomerMenu.PERSONNALDATA);
	}
	
	
    /**
     * Call the validator
     * @param binder call for the validator
     */
    @InitBinder(value={"customerDto"})
    public void initBinderDetail(WebDataBinder binder) {
        binder.setValidator(new CustomerDtoValidator());
    }

}
 